package cn.huiyunche.base.service.interfaces.impl;

import cn.huiyunche.base.service.enums.*;
import cn.huiyunche.base.service.form.SubCWGetForm;
import cn.huiyunche.base.service.framework.security.JwtAuthenicationFilter;
import cn.huiyunche.base.service.framework.utils.HYCUtils;
import cn.huiyunche.base.service.framework.utils.TmsQueueApi;
import cn.huiyunche.base.service.interfaces.*;
import cn.huiyunche.base.service.mappers.DSubsupplierCapacityReportMapper;
import cn.huiyunche.base.service.model.*;
import cn.huiyunche.base.service.utils.DateUtils;
import cn.huiyunche.base.service.vo.*;
import cn.huiyunche.tools.basic.exceptions.BusinessException;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @FileName: cn.huiyunche.service.base.interfaces.impl
 * @Description: Description
 * @author: Aaron
 * @date: 2016/12/6 下午2:07
 */
@Service
public class DSubSupplierServiceImpl implements DSubSupplierService {

    private static final Logger LOGGER = LoggerFactory.getLogger(DSubSupplierServiceImpl.class);

    @Autowired
    private DSubsupplierCapacityReportMapper capacityReportMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private DWaybillService dWaybillService;

    @Autowired
    private TmsQueueService tmsQueueService;

    @Autowired
    private DWaybillStatusHistoryService dWaybillStatusHistoryService;

    private static Jedis jedis = null;

    private static final String D_SUB_SUPPLIER = "D_SUB_SUPPLIER";

    private final String password = "123456a";

    @Autowired
    private SUserSubUserService sUserSubUserService;

    @Autowired
    private DUserLogisticsService dUserLogisticsService;

    @Autowired
    private SUserRouteService sUserRouteService;

    @Autowired
    private CDriverCertinfoService cDriverCertinfoService;

    @Autowired
    private DUserService dUserService;

    @Autowired
    private DUserExtService dUserExtService;

    @Autowired
    private SUserService sUserService;

    @Autowired
    private JwtAuthenicationFilter jwtAuthenticationFilter = null;

    public JwtAuthenicationFilter getJwtAuthenticationFilter() {
        return jwtAuthenticationFilter;
    }

    @Autowired
    private Md5PasswordEncoder passwordEncoder = null;

    public Md5PasswordEncoder getPasswordEncoder() {
        return passwordEncoder;
    }

    @Autowired
    private DUserLicenseService dUserLicenseService;

    @Autowired
    private BLicenseTypeService bLicenseTypeService;

    @Autowired
    private DAreaMappedService dAreaMappedService;

    @Autowired
    private DWaybillApplyResultService dWaybillApplyResultService;

    @Override
    public List<TmsQueueOrderVo> filterDWList(SubCWGetForm form) throws Exception {
        LOGGER.info("getCWList params : {}", form);

        //判断线路申请运单数是否超过没听最大值
        if (this.isExceededTheDailyMaximum(form.getRouteId(), form.getCapacity())) {
            LOGGER.error("filterDWList apply waybills is beyond");
            throw new BusinessException("您申请的运单数已超今日额度！");
//            throw new BusinessException("您申请的运单数已超过当日最大数！");
        }

        //保存上报运力记录
        Long sid = this.add(form);

        //匹配运单
        List<SupplierCWListVo> waybills = dWaybillService.selectByDepaAndDest(form.getOrginName(), form.getDestName(), null);

        //如果为空则可能区域名称不匹配，查询区域匹配信息再查询。如江西省 = 江西
        if (CollectionUtils.isEmpty(waybills)) {
            DAreaMapped orgin = dAreaMappedService.getByAreaCode(form.getOrginCode());
            DAreaMapped dest = dAreaMappedService.getByAreaCode(form.getDestCode());
            if (null != orgin && null != dest) {
                waybills = dWaybillService.selectByDepaAndDest(orgin.getMappedName(), dest.getMappedName(), null);
            }
        }

        List<TmsQueueOrderVo> vos = new ArrayList<>();

        if (CollectionUtils.isNotEmpty(waybills)) {

            if (TmsQueueApi.isStartQueue()) {
                LOGGER.info("filterDWList set queue is start");
                throw new IllegalArgumentException("正在派单，请稍候重试！");
            } else {
                try {
                    //设置队列已开始
                    TmsQueueApi.setStartQueue(true);

                    //匹配移除运单
                    for (SupplierCWListVo bill : waybills) {

                        //从派单队列移除订单添加到分供方的队列
                        TmsQueueOrderVo order = TmsQueueApi.getOrder(bill.getId().toString(), null);
                        if (null != order) {
                            tmsQueueService.removeOrder(bill.getId().toString(), null);

                            TmsQueueOrderVo vo = new TmsQueueOrderVo();
                            vo.setWaybillId(bill.getId().toString());
                            vo.setTmsSerialNo(order.getTmsSerialNo());
                            vo.setFrom(bill.getDepaCity());
                            vo.setTo(bill.getDestCity());
                            vos.add(vo);
                            if (form.getCapacity() == vos.size()) {
                                break;
                            }
                        }
                    }

                    //保存运单申请记录
                    this.buildDWaybillApplyResult(form.getRouteId(), form.getCapacity(), vos);

                    if (CollectionUtils.isNotEmpty(vos)) {

                        //添加到分供方拍单队列
                        this.addToSetOfRedis(vos);

                        List<Long> ids = vos.stream().mapToLong(b -> Long.parseLong(b.getWaybillId())).collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

                        //更新运单用户主键为分供方
                        this.updateUserIdToDWaybill(ids);

                        //更新匹配运单数到上报运力记录
                        Map<String, Object> fieldsMap = new HashMap<>();
                        fieldsMap.put("actualNum", waybills.size());
                        this.update(sid, fieldsMap);
                    }
                } finally {
                    LOGGER.info("filterDWList set queue stop");
                    TmsQueueApi.setStartQueue(false);
                }

            }


        }

        return vos;
    }

    private void buildDWaybillApplyResult(Long routeId, Integer capacity, List<TmsQueueOrderVo> vos) throws Exception {

        LOGGER.info("buildDWaybillApplyResult params : {}", routeId, vos);
        if (null == routeId) {
            LOGGER.error("buildDWaybillApplyResult param sid must not be null");
            throw new IllegalArgumentException("上报运力主键不能为空");
        }

        if (null == capacity) {
            LOGGER.error("buildDWaybillApplyResult param capacity must not be null");
            throw new IllegalArgumentException("申请运单数不能为空");
        }

        DWaybillApplyResult result = new DWaybillApplyResult();
        result.setUserId(userService.getCurrentUser().getId());
        result.setRouteId(routeId);
        result.setApplyAmount(capacity);
        if (CollectionUtils.isNotEmpty(vos)) {
            result.setIsApplySuccess(true);
            result.setActualAmount(vos.size());
        } else {
            result.setIsApplySuccess(false);
            result.setActualAmount(0);
        }

        dWaybillApplyResultService.add(result);
    }

    private boolean isExceededTheDailyMaximum(Long routeId, Integer capacity) throws Exception {
        LOGGER.info("isExceededTheDailyMaximum param : {}, {}", routeId, capacity);
        if (null == routeId) {
            LOGGER.error("isExceededTheDailyMaximum param routeId must not be null");
            throw new IllegalArgumentException("线路主键不能为空");
        }
        if (null == capacity) {
            LOGGER.error("isExceededTheDailyMaximum param capacity must not be null");
            throw new IllegalArgumentException("申请运单数不能为空");
        }

        SUserRoute userRoute = sUserRouteService.selectByPrimary(routeId);
        if (null == userRoute) {
            LOGGER.error("isExceededTheDailyMaximum userRoute must not be null");
            throw new BusinessException("用户线路不能为空");
        }

        if (capacity > userRoute.getMaximumEveryDay()) {
            LOGGER.error("isExceededTheDailyMaximum capacity cannot greater the max ");
            throw new BusinessException("申请运单数不能超出今日额度!");
//            throw new BusinessException("申请运单数不能大于"+userRoute.getMaximumEveryDay()+"单!");
        }

        Long totalOfApply = dWaybillApplyResultService.totalOfApply(userService.getCurrentUser().getId(), true, routeId);

        if (totalOfApply >= userRoute.getMaximumEveryDay()) {
            return true;
        }

        if ((totalOfApply + capacity) > userRoute.getMaximumEveryDay()) {
            LOGGER.error("isExceededTheDailyMaximum capacity plus total cannot greater the max ");
            throw new BusinessException("今日还能申请" + (userRoute.getMaximumEveryDay() - totalOfApply) + "单!");
        }

        return false;
    }

    private void updateUserIdToDWaybill(List<Long> dwIds) throws Exception {
        LOGGER.info("updateUserIdToDWaybill params : {}", dwIds);
        if (CollectionUtils.isEmpty(dwIds)) {
            LOGGER.error("updateUserIdToDWaybill param dwIds must not empty");
            throw new IllegalArgumentException("运单主键不能为空");
        }

        //当前用户主键
        Long userId = userService.getCurrentUser().getId();

        dwIds.forEach(id -> {

            //更新运单状态
            DWaybill waybill = new DWaybill();
            waybill.setId(id);
            waybill.setUserId(userId);
            waybill.setWaybillStatus(DWaybillStatusEnum.DEPARTURE.getValue());
            dWaybillService.updateSelective(waybill);

            //记录运单状态变更记录
            dWaybillStatusHistoryService.add(id, DWaybillStatusTypeEnum.PROCESS.getText(),
                    DWaybillStatusEnum.DEPARTURE.getText(), DWaybillStatusEnum.SAVE.getText(),
                    userId, "分供方运力申请");
        });

    }

    @Override
    public Long add(SubCWGetForm form) throws Exception {
        LOGGER.info("add params : {}", form);

        DSubsupplierCapacityReport capacityReport = new DSubsupplierCapacityReport();
        capacityReport.setUserId(userService.getCurrentUser().getId());
        BeanUtils.copyProperties(form, capacityReport);

        capacityReportMapper.insertSelective(capacityReport);

        return capacityReport.getId();
    }

    @Override
    public void update(Long id, Map<String, Object> fieldsMap) {
        LOGGER.info("update params : {}, {}", id, fieldsMap);
        if (null == id) {
            LOGGER.error("update param id must not be null");
            throw new IllegalArgumentException("主键不能为空");
        }

        if (fieldsMap.isEmpty()) {
            LOGGER.error("update param fieldsMap must not be null");
            throw new IllegalArgumentException("属性不能为空");
        }

        DSubsupplierCapacityReport capacityReport = new DSubsupplierCapacityReport();
        capacityReport.setId(id);

        fieldsMap.forEach((key, value) -> {
            Class<DSubsupplierCapacityReport> clazz = DSubsupplierCapacityReport.class;
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                String methodName = method.getName();

                //setter方法长度不小于4
                if (methodName.length() < 4) {
                    continue;
                }

                //setter方法不是静态的
                if (Modifier.isStatic(method.getModifiers())) {
                    continue;
                }

                //setter方法的返回值为void
                if (!method.getReturnType().equals(Void.TYPE)) {
                    continue;
                }

                //setter方法的参数类型长度不等于
                if (method.getParameterTypes().length != 1) {
                    continue;
                }

                if (methodName.startsWith("set") && Character.isUpperCase(methodName.charAt(3))) {
                    String propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
                    if (key.toString().equals(propertyName)) {
                        method.setAccessible(true);
                        try {
                            method.invoke(capacityReport, value);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        });

        capacityReportMapper.updateByPrimaryKeySelective(capacityReport);
    }

    @Override
    public void addToSetOfRedis(List<TmsQueueOrderVo> vos) {
        LOGGER.info("addToSetOfRedis params : {}", vos);
        jedis = HYCUtils.getJedis();
        try {
            vos.forEach(vo -> vo.setTime(DateUtils.getStringFromDate(new Date(), "yyyy-MM-dd HH:mm:ss")));
            List<String> strings = vos.stream().map(vo -> JSONObject.toJSONString(vo)).collect(Collectors.toList());
            System.out.println("==========strings==========" + strings);
            jedis.sadd(userService.getCurrentUser().getId().toString(), strings.toArray(new String[strings.size()]));
//            jedis.hset(D_SUB_SUPPLIER, userService.getCurrentUser().getId().toString(), resource);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.close();
        }
    }

    @Override
    public Map<String, Object> getWaitingList(PageVo page) throws Exception {
        List<Integer> waybillStatus = Arrays.asList(DWaybillStatusEnum.DEPARTURE.getValue());
        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("userId", userService.getCurrentUser().getId());
        return this.getDWListByConditions(page, waybillStatus, paramsMap);
    }

    @Override
    public Map<String, Object> getExecutionDWList(PageVo page) throws Exception {
        List<Integer> waybillStatus = Arrays.asList(DWaybillStatusEnum.DEPARTURE.getValue(), DWaybillStatusEnum.INTRANSIT.getValue(), DWaybillStatusEnum.DEAL_CAR.getValue());
        Map<String, Object> paramsMap = new HashMap<>();

        List<Long> userIds = this.getSubUserByUser(false);

        if (CollectionUtils.isNotEmpty(userIds)) {
            paramsMap.put("userIds", userIds);

            return this.getDWListByConditions(page, waybillStatus, paramsMap);
        } else {
            paramsMap.put("page", page);
            paramsMap.put("list", new ArrayList<>());
            return paramsMap;
        }
    }

    @Override
    public Map<String, Object> getCompleteDWList(PageVo page) throws Exception {
        List<Integer> waybillStatus = Arrays.asList(DWaybillStatusEnum.COMPLETED.getValue());
        Map<String, Object> paramsMap = new HashMap<>();

        List<Long> userIds = this.getSubUserByUser(false);

        if (CollectionUtils.isNotEmpty(userIds)) {
            paramsMap.put("userIds", userIds);

            return this.getDWListByConditions(page, waybillStatus, paramsMap);
        } else {
            paramsMap.put("page", page);
            paramsMap.put("list", new ArrayList<>());
            return paramsMap;
        }
    }

    //查询用户下的用户主键
    @Override
    public List<Long> getSubUserByUser(Boolean isContainHimself) throws Exception {
        LOGGER.info("getSubUserByUser param : {}", isContainHimself);

        if (null == isContainHimself) {
            isContainHimself = true;
        }

        //用户主键
        Long userId = userService.getCurrentUser().getId();

        //用户下属用户主键
        List<Long> userIds = sUserSubUserService.getUserIdsByUserIdAndType(userId, UserTypeEnum.CONSUMER.getValue());

        //是否包含自己
        if (isContainHimself) {
            if (CollectionUtils.isNotEmpty(userIds)) {
                userIds.add(userId);
            } else {
                userIds = Arrays.asList(userId);
            }
        }
        return userIds;
    }

    @Override
    public Map<String, Object> getDWListByConditions(PageVo page, List<Integer> waybillStatus, Map<String, Object> paramsMap) throws Exception {
        return dWaybillService.getListByPageAndConditions(page, waybillStatus, paramsMap);
    }

    @Override
    public Map<String, Object> getDriversByUser(PageVo page, Boolean isFree) throws Exception {
        LOGGER.info("DSubSupplierServiceImpl.getDriversByUser params : {}, {}", page, isFree);

        Long userId = userService.getCurrentUser().getId();

        //用户下属用户主键
        List<Long> userIds = sUserSubUserService.getUserIdsByUserIdAndType(userId, UserTypeEnum.CONSUMER.getValue());


        if (CollectionUtils.isNotEmpty(userIds)) {

            //如果为真则查询空闲司机
            if (isFree) {
                //移除非空闲司机
                userIds = userIds.stream().filter(id -> {
                    try {
                        return !dWaybillService.hasIntransitDWaybillForUser(id);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return false;
                }).collect(Collectors.toList());
            }

            if (CollectionUtils.isNotEmpty(userIds)) {
                //查询用户司机信息
                Map<String, Object> drivers = userService.getDriversBySUserIdForSupplier(page, userIds);
                return drivers;
            } else {
                Map<String, Object> drivers = new HashMap<>();
                drivers.put("page", page);
                drivers.put("list", new ArrayList<>());
                return drivers;
            }

        } else {
            LOGGER.info("getDriversByUser has no driver");
            if (isFree) {
                throw new BusinessException("没有空闲司机");
            }
        }

        return null;
    }

    @Override
    public Map<String, Object> getLogisticsByDWId(PageVo page, Long dWaybillId) {
        LOGGER.info("getLogisticsByDWId param : {}", dWaybillId);
        if (null == dWaybillId) {
            LOGGER.error("getLogisticsByDWId param dWaybillId must not be null");
            throw new IllegalArgumentException("运单主键不能为空");
        }

        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("dWaybillId", dWaybillId);

        return dUserLogisticsService.getListByDWId(page, paramsMap);

    }

    @Override
    public void specifyDriver(Long wid, Long uid) throws Exception {
        LOGGER.info("specifyDriver params : {}, {}", wid, uid);
        if (null == wid) {
            LOGGER.error("specifyDriver param wid must not be null");
            throw new IllegalArgumentException("运单主键不能为空");
        }
        if (null == uid) {
            LOGGER.error("specifyDriver param uid must not be null");
            throw new IllegalArgumentException("司机主键不能为空");
        }

        //当前用户
        UserShowVo currentUser = userService.getCurrentUser();
        Long currentUserId = currentUser.getId();

        //查询判断运单状态
        DWaybill waybill = dWaybillService.selectByPrimaryKeyAndUserIdAndWaybillStatus(wid, currentUserId, DWaybillStatusEnum.DEPARTURE.getValue());
        if (null == waybill) {
            LOGGER.error("specifyDriver method local variable waybill must not be null");
            throw new BusinessException("运单已指派!");
        }

        waybill.setUserId(0L);
        waybill.setWaybillStatus(DWaybillStatusEnum.SAVE.getValue());
        dWaybillService.updateSelective(waybill);

        //获取司机用户
        SUser driver = userService.getById(uid);

        //判断司机用户是否可用
        if (!sUserService.isDisabled(uid, null, UserTypeEnum.SEND_DRIVER.getValue())) {
            LOGGER.error("DSubSupplierServiceImpl.specifyDriver driver user is disabled");
            throw new BusinessException("司机用户不可用");
        }

        //指派司机主键，更新运单
        try {
            dWaybillService.dispatchDWaybill(waybill, driver.getPhone(), true);
            //从redis中移除待派运单

            this.removeFormSetOfRedis(wid, currentUserId);
        } catch (Exception e) {
            LOGGER.error("specifyDriver method local variable : " + e.getMessage());
            throw new BusinessException(e.getMessage());
        }
    }

    @Override
    public void removeFormSetOfRedis(Long wid, Long currentUserId) {
        LOGGER.info("removeFormSetOfRedis parmas : {}, {}", wid, currentUserId);

        jedis = HYCUtils.getJedis();
        try {
            Set<String> smembers = jedis.smembers(currentUserId.toString());
            if (CollectionUtils.isNotEmpty(smembers)) {
                smembers.forEach(s -> {
                    if (s.contains(wid.toString())) {
                        jedis.srem(currentUserId.toString(), s);
                    }
                });
            }
        } finally {
            jedis.close();
        }
    }

    @Override
    public List<SupplierRouteVo> getRoutes() throws Exception {
        LOGGER.info("getRoutes begin ...");

        //当前用户主键
        Long userId = userService.getCurrentUser().getId();

        //查询用户线路
        List<SUserRoute> routes = sUserRouteService.getListByUserId(userId);
        if (CollectionUtils.isNotEmpty(routes)) {

            List<SupplierRouteVo> vos = new ArrayList<>();

            routes.forEach(r -> {
                SupplierRouteVo vo = new SupplierRouteVo();
                vo.setId(r.getId());
                vo.setCode(r.getOrginCode() + "-" + r.getDestCode());
                vo.setRoute(r.getOrginName() + "-" + r.getDestName());
                vos.add(vo);
            });

            return vos;
        }

        return null;
    }

    @Override
    public Map<String, Object> getDoneByPage(PageVo page) {
        LOGGER.info("select driver 3rd done orders params page : {}.", page);
        try {
            Map<String, Object> paramsMap = new HashMap<>();
            // 获取分供方 下司机ID
            paramsMap.put("userIds", this.getSubUserByUser(true));
            LOGGER.info("select driver 3rd done orders params page : {}, paramsMap : {}.", page, paramsMap);
            String orderByClause = StringUtils.isNotBlank(page.getOrder()) == true ? page.getOrder()
                    : " dw.create_time DESC";
            paramsMap.put("limitStart", page.getStartIndex());
            paramsMap.put("limitEnd", page.getPageSize());
            paramsMap.put("orderByClause", orderByClause);

            List<Integer> statusList = new ArrayList<>();
            statusList.add(DWaybillStatusEnum.COMPLETED.getValue());

            if (CollectionUtils.isNotEmpty(statusList)) {
                paramsMap.put("status", statusList);
            }

            return dWaybillService.selectDriver3rdDone(page, paramsMap);
        } catch (Exception e) {
            LOGGER.error("select driver 3rd done orders params page : {}, error : {}.", page, e);
            throw new BusinessException("分供方查询出车记录异常");
        }
    }

    @Override
    public Map<String, Object> selectAnomalyWaybill(PageVo page) throws Exception {
        List<Integer> waybillStatus = Arrays.asList(DWaybillStatusEnum.EXCEPTION_CONFIRM.getValue());
        Map<String, Object> paramsMap = new HashMap<>();

        paramsMap.put("userIds", this.getSubUserByUser(true));

        return this.getDWListByConditions(page, waybillStatus, paramsMap);
    }

    @Override
    public void addDriver(TmsImportUserVo tmsImportUserVo, UserVo userVo) throws BusinessException, ParseException {
        LOGGER.info("addDriver params tmsImportUserVo: {}, userVo: {}", tmsImportUserVo, userVo);
        //校验身份证号是否存在
        String enCodeIdNo = HYCUtils.encryptBankCard(tmsImportUserVo.getIdCard());
        boolean validIdNo = cDriverCertinfoService.validIdNoExist(enCodeIdNo);
        if (validIdNo) {
            throw new BusinessException("身份证号已经存在");
        }
        //duser表手机号校验
        boolean dUserValidPhone = dUserService.validPhoneExist(tmsImportUserVo.getPhone());
        if (dUserValidPhone) {
            throw new BusinessException("手机号已经存在");
        }
        //suser表手机号校验
        SUser sUser = userService.getByPhone(tmsImportUserVo.getPhone(), Arrays.asList(UserTypeEnum.CONSUMER_DRIVER.getValue(), UserTypeEnum.SEND_DRIVER.getValue()), false);
        if (sUser != null) {
            throw new BusinessException("手机号已经存在");
        }
        //1插入用户表
        Long dUserId = insertDUser(tmsImportUserVo);

        //2用户扩展信息表
        int dUserExtRes = insertDUserExt(tmsImportUserVo, dUserId);
        if (dUserExtRes != 1) {
            throw new BusinessException("数据插入用户扩展信息表失败");
        }

        //3证件表
        int dUserLicenseRes = insertDUserLicense(tmsImportUserVo, dUserId);

        //4用户表
        Long sUserId = insertSUser(tmsImportUserVo);

        //5用户下属用户关联表
        int sUserSubUserRes = insertSUserSubUser(userVo, sUserId);
        if (sUserSubUserRes != 1) {
            throw new BusinessException("数据插入用户下属用户关联表失败");
        }
    }

    /**
     * 1.插入duser表
     *
     * @param tmsImportUserVo
     * @return
     */
    private Long insertDUser(TmsImportUserVo tmsImportUserVo) {
        DUser dUser = null;
        if (StringUtils.isNotBlank(tmsImportUserVo.getdUserId())) {
            //编辑
            dUser = dUserService.selectByPrimaryKey(Long.parseLong(tmsImportUserVo.getdUserId()));
            if (!tmsImportUserVo.getPhone().equals(dUser.getLoginName())) {
                //手机号校验
                boolean validPhone = dUserService.validPhoneExist(tmsImportUserVo.getPhone());
                if (validPhone) {
                    throw new BusinessException("手机号已经存在");
                }
            }
        } else {
            //添加
            dUser = new DUser();
            dUser.setPwd(passwordEncoder.encodePassword(password, jwtAuthenticationFilter.getSecureKey()));
            dUser.setType(TmsUserTypeEnum.DRIVER.getValue());
            dUser.setEnable(true);
        }
        dUser.setLoginName(tmsImportUserVo.getPhone());

        if (StringUtils.isNotBlank(tmsImportUserVo.getdUserId())) {
            int res = dUserService.updateByPrimaryKeySelective(dUser);
            if (res != 1) {
                throw new BusinessException("数据插入用户表失败");
            }
        } else {
            int res = dUserService.insertSelective(dUser);
            if (res != 1) {
                throw new BusinessException("数据插入用户表失败");
            }
        }

        return dUser.getId();
    }

    /**
     * 2.插入用户扩展信息表
     *
     * @param tmsImportUserVo
     * @return
     */
    private int insertDUserExt(TmsImportUserVo tmsImportUserVo, Long dUserId) {
//        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");注释的为2016-12-13 去掉的字段
        DUserExt dUserExt = null;
        if (StringUtils.isNotBlank(tmsImportUserVo.getdUserId())) {
            DUserExtExample dUserExtExample = new DUserExtExample();
            dUserExtExample.createCriteria().andUserIdEqualTo(Long.parseLong(tmsImportUserVo.getdUserId()));
            List<DUserExt> list = dUserExtService.selectByExample(dUserExtExample);
            if (list.size() != 1) {
                throw new BusinessException("没有找到用户对应的信息");
            }
            dUserExt = list.get(0);
        } else {
            dUserExt = new DUserExt();
            dUserExt.setUserId(dUserId);
        }
        dUserExt.setUserName(tmsImportUserVo.getRealName());
        dUserExt.setRealName(tmsImportUserVo.getRealName());
//        dUserExt.setBirthplace(tmsImportUserVo.getNativePlace());
//        dUserExt.setBirthday(dateFormat.parse(tmsImportUserVo.getBirthday()));
        dUserExt.setIdNo(tmsImportUserVo.getIdCard());
//        dUserExt.setJobNo(tmsImportUserVo.getJobno());
        dUserExt.setPhone(tmsImportUserVo.getPhone());
//        dUserExt.setHomePhone(tmsImportUserVo.getTelephone());
//        dUserExt.setHomeAddress(tmsImportUserVo.getAddress());
//        dUserExt.setGuarantor(tmsImportUserVo.getGuarantor());
        if (StringUtils.isNotBlank(tmsImportUserVo.getdUserId())) {
            return dUserExtService.updateByPrimaryKeySelective(dUserExt);
        } else {
            return dUserExtService.insertSelective(dUserExt);
        }

    }

    /**
     * 3.插入证件表
     *
     * @param tmsImportUserVo
     * @param dUserId
     * @return
     * @throws ParseException
     */
    private int insertDUserLicense(TmsImportUserVo tmsImportUserVo, Long dUserId) throws ParseException {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        BLicenseTypeExample bLicenseTypeExample = new BLicenseTypeExample();
        String[] arr = tmsImportUserVo.getLicenceIds().split(",");
        List<Integer> licenceIds = new ArrayList<Integer>();
        for (int i = 0; i < arr.length; i++) {
            licenceIds.add(Integer.parseInt(arr[i]));
        }
        bLicenseTypeExample.createCriteria().andIdIn(licenceIds);
        List<BLicenseType> bLicenseTypeList = bLicenseTypeService.selectByExample(bLicenseTypeExample);
        if (arr.length != licenceIds.size()) {
            throw new BusinessException("驾照类型不存在");
        }
        int res = 0;
        for (BLicenseType bLicenseType : bLicenseTypeList) {
            DUserLicense dUserLicense = new DUserLicense();
            dUserLicense.setUserId(dUserId);
            dUserLicense.setSysLicenseId(bLicenseType.getId());
            dUserLicense.setLicenseDept("发证机关");
            dUserLicense.setReceiveTime(dateFormat.parse(tmsImportUserVo.getReceiveDate()));
            dUserLicense.setLicenseName(bLicenseType.getLicenseName());
            int blicenseRes = dUserLicenseService.insertSelective(dUserLicense);
            res += blicenseRes;
        }
        return res;

    }


    /**
     * 4.插入用户表
     *
     * @param tmsImportUserVo
     * @return
     * @throws ParseException
     */
    private Long insertSUser(TmsImportUserVo tmsImportUserVo) throws ParseException {
        SUser sUser = null;
        if (StringUtils.isNotBlank(tmsImportUserVo.getsUserId())) {
            sUser = sUserService.selectByPrimaryKey(Long.parseLong(tmsImportUserVo.getsUserId()));
            //校验手机号
            if (!sUser.getPhone().equals(tmsImportUserVo.getPhone())) {
                boolean validPhoneExist = sUserService.validPhoneExist(tmsImportUserVo.getPhone(), UserTypeEnum.CONSUMER_DRIVER.getValue());
                if (validPhoneExist) {
                    throw new BusinessException("手机号已经存在");
                }
            }
        } else {
            sUser = new SUser();
            sUser.setPwd(passwordEncoder.encodePassword(password, jwtAuthenticationFilter.getSecureKey()));
            sUser.setEnable(EnabledEnum.T.getValue());
        }
        sUser.setUserType(UserTypeEnum.CONSUMER_DRIVER.getValue());
        sUser.setName(tmsImportUserVo.getRealName());
        sUser.setRealName(tmsImportUserVo.getRealName());
        sUser.setPhone(tmsImportUserVo.getPhone());
        int res;
        if (StringUtils.isNotBlank(tmsImportUserVo.getsUserId())) {
            res = sUserService.updateByPrimaryKeySelective(sUser);
        } else {
            res = sUserService.insertSelective(sUser);
        }
        if (res != 1) {
            throw new BusinessException("数据插入用户表失败");
        }
        return sUser.getId();
    }

    /**
     * 5.插入用户下属用户关联表
     *
     * @param userVo
     * @param sUserId
     * @return
     */
    private int insertSUserSubUser(UserVo userVo, Long sUserId) {
        SUserSubUser sUserSubUser = new SUserSubUser();
        sUserSubUser.setUserId(userVo.getId());
        sUserSubUser.setSubUserId(sUserId);
        sUserSubUser.setEnable(EnabledEnum.T.getValue() == "T");
        return sUserSubUserService.insertSelective(sUserSubUser);
    }

    /**
     * 编辑司机
     *
     * @param tmsImportUserVo
     * @throws BusinessException
     * @throws ParseException
     */
    public void editDriver(TmsImportUserVo tmsImportUserVo) throws Exception {
        LOGGER.info("editDriver params tmsImportUserVo: {}", tmsImportUserVo);
        //校验权限
        Long currentUserId = userService.getCurrentUserVo().getId();
        boolean validCurrentAndUser = sUserSubUserService.validCurrentUserEqualSuserId(currentUserId, Long.parseLong(tmsImportUserVo.getsUserId()));
        if (!validCurrentAndUser) {
            throw new BusinessException("当前登陆人不可操作此用户");
        }
        //校验身份证号是否存在
        String enCodeIdNo = HYCUtils.encryptBankCard(tmsImportUserVo.getIdCard());
        boolean validIdNo = cDriverCertinfoService.validIdNoExist(enCodeIdNo);
        if (validIdNo) {
            throw new BusinessException("身份证号已经存在");
        }
        //1用户表信息 -----手机号修改的话 则修改用户名
        insertDUser(tmsImportUserVo);
        //2更新用户信息扩展表信息
        int dUserExtRes = insertDUserExt(tmsImportUserVo, null);

        //3更新用户证件表信息   先删除所有的，然后重新添加
        int dUserLicenseRes = dUserLicenseService.deleteByUserId(Long.parseLong(tmsImportUserVo.getdUserId()));
        insertDUserLicense(tmsImportUserVo, Long.parseLong(tmsImportUserVo.getdUserId()));
        //4更新用户表信息
        insertSUser(tmsImportUserVo);
        //5用户关联下属关系表  －－－－不用更新

    }

    /**
     * 删除司机
     *
     * @param dUserId
     * @param sUserId
     * @throws BusinessException
     */
    public void deleteDriver(String dUserId, String sUserId) throws Exception {
        LOGGER.info("deleteDriver params dUserId: {} ,sUserId", dUserId, sUserId);
        //校验权限
        Long currentUserId = userService.getCurrentUserVo().getId();
        boolean validCurrentAndUser = sUserSubUserService.validCurrentUserEqualSuserId(currentUserId, Long.parseLong(sUserId));
        if (!validCurrentAndUser) {
            throw new BusinessException("当前登陆人不可操作此用户");
        }
        //1 删除用户表dUserId
        int dUserRes = dUserService.deleteByPrimaryKey(Long.parseLong(dUserId));
        if (dUserRes != 1) {
            throw new BusinessException("数据删除用户表失败");
        }

        //2 删除用户扩展信息表dUserId
        int dUserExtRes = dUserExtService.deleteByUserId(Long.parseLong(dUserId));
        if (dUserExtRes != 1) {
            throw new BusinessException("数据删除用户信息扩展表失败");
        }

        //3 删除用户证件表dUserId
        int dUserLicenseRes = dUserLicenseService.deleteByUserId(Long.parseLong(dUserId));

        //4 删除用户表sUserId
        int sUserRes = sUserService.deleteByPrimaryKey(Long.parseLong(sUserId));
        if (sUserRes != 1) {
            throw new BusinessException("数据删除用户表失败");
        }

        //5 删除用户关联下属用户表sUserId
        int sUserSubRes = sUserSubUserService.deleteBySubUserId(Long.parseLong(sUserId));
        if (sUserSubRes != 1) {
            throw new BusinessException("数据删除用户关联下属用户表失败");
        }

    }

    @Override
    public List<DWaybillPriceDetailVo> selectPriceById(Long waybillId) {
        LOGGER.info("select dwaybill 3rd price detail params waybillId : {}.", waybillId);
        try {
            return dWaybillService.selectPriceById(waybillId);
        } catch (Exception e) {
            LOGGER.error("select dwaybill 3rd price detail params waybillId : {}, e : {}.", waybillId, e);
            throw new BusinessException("查询运单费用明细异常");
        }
    }

    @Override
    public void recoverDWaybill() throws Exception {

        //查询所以分供方用户
        List<Long> userIds = userService.getUserIdsByType(UserTypeEnum.CONSUMER.getValue());

        //查询分供方用户的运单
        if (CollectionUtils.isNotEmpty(userIds)) {
            List<DWaybill> bills = dWaybillService.getListByUsersId(userIds);

            //移除运单的用户
            if (CollectionUtils.isNotEmpty(bills)) {
                bills.forEach(b -> {
                    Long userId = b.getUserId();
                    b.setUserId(0L);
                    b.setWaybillStatus(DWaybillStatusEnum.SAVE.getValue());
                    dWaybillService.updateSelective(b);

                    //移除redis中分供方的运单
                    this.removeFormSetOfRedis(b.getId(), userId);
                });
            }
        }

    }

    @Override
    public DWaybillDetailVo getById(long id) throws Exception {

        return dWaybillService.getById(id);
    }
}
